package com.syxp.pda.core.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.syxp.pda.core.command.CriteriaCommand;
import com.syxp.pda.core.command.QueryFilter;
import com.syxp.pda.core.dao.GenericDao;
import com.syxp.pda.core.web.PagingBean;

public class GenericDaoImpl<T,PK extends Serializable> extends HibernateDaoSupport implements GenericDao<T,Integer>{

	private Class<T> persistType ;
	
	public GenericDaoImpl(Class<T> persistType){
		this.persistType = persistType ;
	}
	
	public GenericDaoImpl(){
		
	}
	public Class<T> getPersistType() {
		return persistType;
	}
	
	public void setPersistType(Class<T> persistType) {
		this.persistType = persistType;
	}

	@Override
	public T save(T paramT) {
		getHibernateTemplate().saveOrUpdate(paramT);
		return paramT;
	}

	@Override
	public T update(T paramT) {
		getHibernateTemplate().update(paramT) ;
		return paramT ;
	}
	@Override
	public T merge(T paramT) {
		getHibernateTemplate().merge(paramT);
		return paramT;
	}

	@Override
	public T get(Integer paramPK) {
		return (T)getHibernateTemplate().get(persistType.getName(), paramPK) ;
	}

	@Override
	public void remove(Integer paramPK) {
		getHibernateTemplate().delete(get(paramPK)) ;
	}

	@Override
	public void remove(T paramT) {
		getHibernateTemplate().delete(paramT) ;
	}

	@Override
	public void evict(T paramT) {
		getHibernateTemplate().evict(paramT) ;
	}

	@Override
	public List<T> getAll() {
		return (List<T>)getHibernateTemplate().execute(new HibernateCallback(){

			@Override
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query = getSession().createQuery("from "+GenericDaoImpl.this.persistType.getName()) ;
				return query.list();
			}
		});
	}

	@Override
	public List<T> getAll(final PagingBean paramPagingBean) {
		return (List<T>)getHibernateTemplate().execute(new HibernateCallback(){

			@Override
			public Object doInHibernate(Session arg0)
					throws HibernateException, SQLException {
				Query query = getSession().createQuery("from "+GenericDaoImpl.this.persistType.getName())
				.setFirstResult(paramPagingBean.getStart()).setMaxResults(paramPagingBean.getPageSize()) ;
				return query.list();
			}
			
		});
	}

	@Override
	public List<T> getAll(final QueryFilter paramQueryFilter) {
		return (List<T>) getHibernateTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session arg0) throws HibernateException,
					SQLException {
				Criteria criteria = getSession().createCriteria(GenericDaoImpl.this.persistType) ;
				return setQueryByCriteria(criteria,paramQueryFilter);
			}
		}) ;
	}

	@Override
	public List<T> getAll_no(QueryFilter paramQueryFilter) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public List<T> findByHql(String paramString, Object[] paramArrayOfObject) {
		return null;
	}

	@Override
	public List<T> findByHql(String paramString, Object[] paramArrayOfObject,
			PagingBean paramPagingBean) {
		return null;
	}

	@Override
	public List<T> findByHql(String paramString, Object[] paramArrayOfObject,
			int paramInt1, int paramInt2) {
		// TODO Auto-generated method stub
		return null;
	}

	protected List<T> setQueryByCriteria(Criteria criteria,QueryFilter filter) {
		
		for(CriteriaCommand command : filter.getCriterias()){
			command.execute(criteria) ;
		}
		if(filter.getPagingBean()!=null){
//			int v_endrownum = filter.getPagingBean().getStart()*filter.getPagingBean().getPageSize();
//			int v_startrownum = v_endrownum - filter.getPagingBean().getPageSize() + 1;
			criteria.setFirstResult(filter.getPagingBean().getStart()) ;
			criteria.setMaxResults(filter.getPagingBean().getPageSize()) ;
		}
		if(filter.getOrderProperty().size()>0){
			for(String p : filter.getOrderProperty())
			criteria.addOrder(Order.asc(p)) ;
		}
		return criteria.list();
	}

	@Override
	public Object executeHql(String hqlStr, Object[] paramArrayOfObject) {
		
		Query query = getSession().createQuery(hqlStr) ;
		for(int i=0 ; i<paramArrayOfObject.length ; i++) {
			query.setParameter(i, paramArrayOfObject[i]) ;
		}
		return query.executeUpdate() ;
	}

	public Long getTotalProperty(final QueryFilter filter) {
		
		if(filter!=null){
			return (Long)getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session arg0) throws HibernateException,
						SQLException {
					Criteria criteria = getSession().createCriteria(GenericDaoImpl.this.persistType) ;
					for(CriteriaCommand command : filter.getCriterias()){
						command.execute(criteria) ;
					}
					criteria.setProjection(Projections.rowCount()) ;
					return criteria.uniqueResult() ;
				}
			}) ;
		}else{
				return (Long)getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session arg0) throws HibernateException,
						SQLException {
					Criteria criteria = getSession().createCriteria(GenericDaoImpl.this.persistType) ;
					criteria.setProjection(Projections.rowCount()) ;
					return criteria.uniqueResult() ;
				}
			}) ;
		}
	}
}
